package bootstrap

import (
	"common/global"
	"common/tools"
	"context"
	"fmt"
	"github.com/kataras/golog"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/middleware/cors"
	"github.com/kataras/iris/v12/middleware/recover"
	"os"
	"os/signal"
	"syscall"
	"time"
)

type Bootstrapper struct {
	*iris.Application
	AppName      string
	AppOwner     string
	AppSpawnDate time.Time
	Api          iris.Party
}

func (b *Bootstrapper) Configure(cfgArray ...Configurator) {
	for _, cfg := range cfgArray {
		cfg(b)
	}
}

func (b *Bootstrapper) setupErrorHandlers() {
	b.OnAnyErrorCode(func(ctx iris.Context) {
		var code global.Code
		switch ctx.GetStatusCode() {
		case iris.StatusNotFound:
			code = global.CodeNotFount
		default:
			code = global.CodeFailure
		}
		tools.Error_(ctx, ctx.GetStatusCode(), code, "服务器错误：%v", ctx.GetErr())
	})
}

type Configurator func(*Bootstrapper)

func New(appName, appOwner string, cfgArray ...Configurator) *Bootstrapper {
	b := &Bootstrapper{
		Application:  iris.New(),
		AppName:      appName,
		AppOwner:     appOwner,
		AppSpawnDate: time.Now(),
	}
	b.Configure(cfgArray...)
	return b
}

// localhost:10087/statsviz/
// 实时可视化Go Runtime指标，这个Go库超赞
func (b *Bootstrapper) setupMonitor() {
	//statsvizPath := "/statsviz/"
	//serveRoot := statsviz.IndexAtRoot(statsvizPath)
	//serveWS := statsviz.NewWsHandler(time.Second * 6)
	//b.UseRouter(func(ctx iris.Context) {
	//	if strings.HasPrefix(ctx.Path(), statsvizPath+"ws") {
	//		serveWS(ctx.ResponseWriter(), ctx.Request())
	//	} else if strings.HasPrefix(ctx.Path(), statsvizPath) {
	//		serveRoot(ctx.ResponseWriter(), ctx.Request())
	//	} else {
	//		ctx.Next()
	//	}
	//})
}

// Bootstrap prepares our application.
//
// Returns itself.
func (b *Bootstrapper) Bootstrap() *Bootstrapper {
	//b.HandleDir("/", static.AssetFile())
	//b.HandleDir("/static", static.AssetFile())
	//b.setupErrorHandlers() // todo: 不知道为啥报错
	b.setupMonitor()
	b.setupGlobal()
	b.setupCros()
	// middleware, after static files
	b.Use(recover.New())
	b.setupApi()
	return b
}

func (b *Bootstrapper) setupCros() {
	crs := cors.New().AllowOrigin("*").Handler()
	b.UseRouter(crs)
}

func (b *Bootstrapper) setupApi() {
	api := b.Party("/api/admin")
	//api.Use(middleware.ServeHTTP)
	b.Api = api
}

func (b *Bootstrapper) setupGlobal() {
	b.UseGlobal(func(ctx iris.Context) {
		// 设置上下文开始时间，可用于计算HTTP请求耗时
		ctx.Values().Set(global.RequestStartTimeKey, time.Now().UnixMicro())
		ctx.Next()
	})
	b.DoneGlobal(done)
}

func (b *Bootstrapper) Listen() {
	idleConnsClosed := make(chan struct{})
	go func() {
		ch := make(chan os.Signal, 1)
		signal.Notify(ch,
			os.Interrupt,   // kill -SIGINT XXXX or Ctrl+c
			syscall.SIGINT, // register that too, it should be ok
			syscall.SIGQUIT,
			// os.Kill,         // is equivalent with the syscall.Kill
			// syscall.SIGKILL, // register that too, it should be ok
			syscall.SIGTERM, // kill -SIGTERM XXXX
		)
		select {
		case aa := <-ch:
			fmt.Printf("shutdown... %v", aa)
			golog.Errorf("关闭了，曹")

			timeout := 3 * time.Second
			ctx, cancel := context.WithTimeout(context.Background(), timeout)
			defer cancel()
			b.Shutdown(ctx)
			close(idleConnsClosed)
		default:
		}
	}()
	// if err := app.Listen(fmt.Sprintf("0.0.0.0:%d", global.GConfig.App.Own.Port),
	// 	iris.WithoutInterruptHandler,
	// 	iris.WithConfiguration(global.GConfig.App.Configuration)); err != nil {
	// 	golog.Fatalf("%s启动失败,原因:%v", b.AppName, err)
	// }
	if err := b.Run(
		iris.Addr(fmt.Sprintf("0.0.0.0:%d", global.GConfig.App.Own.Port)),
		iris.WithoutInterruptHandler,
		iris.WithConfiguration(global.GConfig.App.Configuration),
	); err != nil {
		golog.Fatalf("%s启动失败,原因:%v", b.AppName, err)
	}
	<-idleConnsClosed
}
